package com.jkgl.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jkgl.common.core.domain.R;
import com.jkgl.common.utils.SecurityUtils;
import com.jkgl.entity.UserInfoDayEntity;
import com.jkgl.entity.UserInfoSelfEntity;
import com.jkgl.model.result.HealthSuggestion;
import com.jkgl.model.userinfoday.UserInfoTodayVO;
import com.jkgl.service.HealthAdvisorService;
import com.jkgl.util.ASEUtils;
import com.jkgl.service.UserInfoDayService;
import com.jkgl.service.UserInfoSelfService;
import com.jkgl.util.DurationUtil;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


@RestController
@RequiredArgsConstructor
@Slf4j
@RequestMapping("report")
public class ReportDecryptController {
    private final UserInfoDayService dayService;
    private final UserInfoSelfService selfService;
    private final HealthAdvisorService advisorService;


    /**
     *
     * @param encrypt 密钥  userId|LocalDate
     *                路径传参存在问题 密钥如果加码以后携带 ‘FRPmrlFsCfAN0G959I1m6/gJNrNEraMA’ 则接口不存在
     *                改为Query传参
     * @return 传回时间默认减一得到当天时间
     * @throws Exception
     */
    @GetMapping("/decryptDay")
    @ApiOperation("解密信息返回数据")
    public R decryptDay( String encrypt) {
        String datas;
        try {
            datas = ASEUtils.decrypt(encrypt);
        }catch (Exception e){
            return R.fail("参数错误，请检查是否正确！");
        }
        String[] data = datas.split("\\|");
        LocalDate parse = LocalDate.parse(data[1]);
        QueryWrapper<UserInfoDayEntity> dayQuery = new QueryWrapper<>();
        dayQuery.lambda().eq(UserInfoDayEntity::getUserId,data[0])
//                时间不好控制 排序
                .eq(UserInfoDayEntity::getCreateTime,parse.minusDays(1));
        UserInfoDayEntity day = dayService.getOne(dayQuery);
        dayQuery.clear();
        UserInfoSelfEntity infoSelf = selfService.getInfoSelf(Long.valueOf(data[0]));
        dayQuery.lambda().eq(UserInfoDayEntity::getUserId,data[0])
                .ge(UserInfoDayEntity::getCreateTime,day.getCreateTime().minusDays(1))
                .le(UserInfoDayEntity::getCreateTime,day.getCreateTime())
                .orderByDesc(UserInfoDayEntity::getCreateTime);
        List<UserInfoDayEntity> list = dayService.list(dayQuery);
        List<UserInfoTodayVO> vos = BeanUtil.copyToList(list, UserInfoTodayVO.class);
        if(vos.get(0) == null){
            return R.fail("昨日信息未登记！！");
        }
        for( UserInfoTodayVO vo : vos){
            long subTime = DurationUtil.timeDiff(vo.getSleepTime(), vo.getWakeupTime());
            vo.setTimeSubHour((int) (subTime/60));
            vo.setTimeSubMinutes((int) (subTime%60));
        }
        if(vos.size() < 2){
            vos.add(null);
        }
//        if(!userId.equals(day.getUserId())){
//            return R.fail("请求错误，请确定参数是否正确");
//        }
        List<HealthSuggestion> healthSuggestions = advisorService.generateDailyAdvice(vos.get(0), vos.get(1), infoSelf);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("today",vos.get(0));
        jsonObject.put("yesterday",vos.get(1));
        jsonObject.put("suggestion",healthSuggestions);
        return R.ok(jsonObject);
    }


    /**
     *
     * @param encrypt 密钥  userId|LocalDate
     * @return--传回时间默认减一得到周天时间
     * @throws Exception
     */
    @GetMapping("/decryptWeek")
    @ApiOperation("解密信息返回数据")
    public R decryptWeek( String encrypt) {
        String datas;
        try {
            datas = ASEUtils.decrypt(encrypt);
        }catch (Exception e){
            return R.fail("参数错误，请检查是否正确！");
        }
        String[] data = datas.split("\\|");
        LocalDate parse = LocalDate.parse(data[1]).minusDays(1);
        Map<String , UserInfoTodayVO> map = new HashMap<>();
        map.put(parse.toString(),null);
        LocalDate Sunday = parse;
//        遍历到MAP
        for(int i=0; i<6;i++){
            Sunday = Sunday.plusDays(1);
            map.put(Sunday.toString(),null);
        }
        QueryWrapper<UserInfoDayEntity> dayQuery = new QueryWrapper<>();
        dayQuery.lambda().eq(UserInfoDayEntity::getUserId,data[0])
//                时间不好控制 排序
                .le(UserInfoDayEntity::getCreateTime,parse)
                .ge(UserInfoDayEntity::getCreateTime,Sunday)
                .orderByDesc(UserInfoDayEntity::getCreateTime);
        List<UserInfoDayEntity> list = dayService.list(dayQuery);
        List<UserInfoTodayVO> vos = BeanUtil.copyToList(list, UserInfoTodayVO.class);
        UserInfoSelfEntity infoSelf = selfService.getInfoSelf(Long.valueOf(data[0]));
        for(UserInfoTodayVO entity : vos){
            if(map.containsKey(entity.getCreateTime().toString())){
                long time = DurationUtil.timeDiff(entity.getSleepTime(), entity.getWakeupTime());
                entity.setTimeSubHour((int) (time/60));
                entity.setTimeSubMinutes((int) (time%60));
                map.put(entity.getCreateTime().toString(),entity);
            }
        }
        List<HealthSuggestion> healthSuggestions = weekSuggestion(vos, infoSelf);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("days",map);
        jsonObject.put("self",infoSelf);
        jsonObject.put("suggestions",healthSuggestions);
        return R.ok(jsonObject);
    }


    /**
     * 传id
     * @return
     */
    @ApiOperation("用户日报--网页点击某天信息查看")
    @GetMapping("userReport/Day/{id}")
    public R userReport(@PathVariable("id") String id){
        Long userId = SecurityUtils.getUserId();
        QueryWrapper<UserInfoDayEntity> queryWrapper = new QueryWrapper<>();
        UserInfoDayEntity day = dayService.getById(id);
        UserInfoSelfEntity infoSelf = selfService.getInfoSelf(userId);
        queryWrapper.lambda().eq(UserInfoDayEntity::getUserId,userId)
                .ge(UserInfoDayEntity::getCreateTime,day.getCreateTime().minusDays(1))
                .le(UserInfoDayEntity::getCreateTime,day.getCreateTime())
                .orderByDesc(UserInfoDayEntity::getCreateTime);
        List<UserInfoDayEntity> list = dayService.list(queryWrapper);
        List<UserInfoTodayVO> vos = BeanUtil.copyToList(list, UserInfoTodayVO.class);
        for( UserInfoTodayVO vo : vos){
            long subTime = DurationUtil.timeDiff(vo.getSleepTime(), vo.getWakeupTime());
            vo.setTimeSubHour((int) (subTime/60));
            vo.setTimeSubMinutes((int) (subTime%60));
        }
        if(vos.size() < 2){
            vos.add(null);
        }
        if(!userId.equals(day.getUserId())){
            return R.fail("请求错误，请确定参数是否正确");
        }
        List<HealthSuggestion> healthSuggestions = advisorService.generateDailyAdvice(vos.get(0), vos.get(1), infoSelf);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("today",vos.get(0));
        jsonObject.put("yesterday",vos.get(1));
        jsonObject.put("suggestion",healthSuggestions);
        return R.ok(jsonObject);
    }


    /**
     * 目前--前端准备element 的时间组件可以精确到周
     * 传入字符串
     * Mon Mar 17 2025 00:00:00 GMT+0800
     */
    @ApiOperation("用户周报--网页点击某周信息查看")
    @GetMapping("userReport/Week")
    public R userReportWeek(String zondDate){
        Long userId = SecurityUtils.getUserId();
        LocalDate Monday = LocalDate.parse(zondDate);
        Map<String , UserInfoTodayVO> map = new HashMap<>();
        map.put(Monday.toString(),null);
        LocalDate Sunday = Monday;
//        遍历到MAP
        for(int i=0; i<6;i++){
            Sunday = Sunday.plusDays(1);
            map.put(Sunday.toString(),null);
        }
        QueryWrapper<UserInfoDayEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserInfoDayEntity::getUserId,userId)
                .ge(UserInfoDayEntity::getCreateTime,Monday)
                .le(UserInfoDayEntity::getCreateTime,Sunday);
        List<UserInfoDayEntity> list = dayService.list(queryWrapper);
        List<UserInfoTodayVO> vos = BeanUtil.copyToList(list, UserInfoTodayVO.class);
        UserInfoSelfEntity infoSelf = selfService.getInfoSelf(userId);
        for(UserInfoTodayVO entity : vos){
            if(map.containsKey(entity.getCreateTime().toString())){
                long time = DurationUtil.timeDiff(entity.getSleepTime(), entity.getWakeupTime());
                entity.setTimeSubHour((int) (time/60));
                entity.setTimeSubMinutes((int) (time%60));
                map.put(entity.getCreateTime().toString(),entity);
            }
        }
//        if
        List<HealthSuggestion> healthSuggestions = weekSuggestion(vos, infoSelf);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("days",map);
        jsonObject.put("self",infoSelf);
        jsonObject.put("suggestions",healthSuggestions);
        return R.ok(jsonObject);
    }



    public List<HealthSuggestion> weekSuggestion(List<UserInfoTodayVO> list, UserInfoSelfEntity self) {
        // 统计指标初始化
        int stepComplianceDays = 0;      // 步数达标天数
        int maxStepContinuous = 0;       // 最大连续达标天数
        int currentStepStreak = 0;

        int sleepDurationGoodDays = 0;   // 睡眠时长合格天数（7-9小时）
        int lateSleepDays = 0;           // 晚于22点入睡天数
        LocalDateTime earliestBedtime = null;
        LocalDateTime latestBedtime = null;

        int exerciseGoalDays = 0;        // 运动时长达标天数
        double maxExercise = 0.0;
        double minExercise = Double.MAX_VALUE;
        int currentExerciseStreak = 0;

        int maxSbp = Integer.MIN_VALUE;  // 收缩压极值
        int minSbp = Integer.MAX_VALUE;
        int highBpDays = 0;              // 收缩压超标天数（>140）

        // === 新增睡眠质量统计 ===
        double totalDeepSleep = 0.0;
        double totalRemSleep = 0.0;
        int lowDeepSleepDays = 0;    // 深度睡眠不足天数（<15%）
        int lowRemSleepDays = 0;      // REM睡眠不足天数（<20%）
        int highLightSleepDays = 0;  // 浅睡过高天数（>60%）

        for (UserInfoTodayVO vo : list) {
            // === 步数分析 ===
            int step = Integer.parseInt(vo.getStepNumber());
            int targetStep = Integer.parseInt(self.getTargetStep());
            if (step >= targetStep - 100) {
                stepComplianceDays++;
                currentStepStreak++;
                maxStepContinuous = Math.max(maxStepContinuous, currentStepStreak);
            } else {
                currentStepStreak = 0;
            }

            // === 睡眠分析 ===
            int sleepHours = vo.getTimeSubHour();
            if (sleepHours >= 7 && sleepHours <= 9) {
                sleepDurationGoodDays++;
            }
            if (vo.getSleepTime().getHour() >= 22) {
                lateSleepDays++;
            }
            // 记录最早/最晚入睡时间
            if (earliestBedtime == null || vo.getSleepTime().isBefore(earliestBedtime)) {
                earliestBedtime = vo.getSleepTime();
            }
            if (latestBedtime == null || vo.getSleepTime().isAfter(latestBedtime)) {
                latestBedtime = vo.getSleepTime();
            }

            // === 运动分析 ===
            double exerciseTime = vo.getSportTimeLong();
            if (exerciseTime >= self.getExerciseMinutesGoal()) {
                exerciseGoalDays++;
                currentExerciseStreak++;
            } else {
                currentExerciseStreak = 0;
            }
            maxExercise = Math.max(maxExercise, exerciseTime);
            minExercise = Math.min(minExercise, exerciseTime);

            // === 血压分析 ===
            maxSbp = Math.max(maxSbp, vo.getSbp());
            minSbp = Math.min(minSbp, vo.getSbp());
            if (vo.getSbp() > 140) highBpDays++;

            // === 新增睡眠质量统计 ===
            // 深度睡眠分析
            if (vo.getDeepSleepPercentage() < 15.0) {
                lowDeepSleepDays++;
            }
            totalDeepSleep += vo.getDeepSleepPercentage();

            // REM睡眠分析
            if (vo.getRemSleepPercentage() < 20.0) {
                lowRemSleepDays++;
            }
            totalRemSleep += vo.getRemSleepPercentage();

            // 浅睡眠分析
            if (vo.getLightSleepPercentage() > 60.0) {
                highLightSleepDays++;
            }
        }

        // === 生成建议 ===
        List<HealthSuggestion> suggestions = new ArrayList<>();

        // 1. 步数建议
        generateStepSuggestions(suggestions, stepComplianceDays, maxStepContinuous, self.getTargetStep());

        // 2. 睡眠建议
        generateSleepSuggestions(suggestions, sleepDurationGoodDays, lateSleepDays, earliestBedtime, latestBedtime);

        // 3. 运动建议
        generateExerciseSuggestions(suggestions, exerciseGoalDays, maxExercise, minExercise, self.getExerciseMinutesGoal());

        // 4. 血压建议
        generateBpSuggestions(suggestions, maxSbp, highBpDays);

        // 计算周平均值
        double avgDeepSleep = totalDeepSleep / list.size();
        double avgRemSleep = totalRemSleep / list.size();

        // === 生成建议（新增睡眠质量部分）===
        generateSleepQualitySuggestions(suggestions,
                avgDeepSleep,
                avgRemSleep,
                lowDeepSleepDays,
                lowRemSleepDays,
                highLightSleepDays);

        // 按优先级排序（数值越小越优先）
        suggestions.sort(Comparator.comparingInt(HealthSuggestion::getPriority));

        return suggestions;
    }

    private void generateStepSuggestions(List<HealthSuggestion> list,
                                         int complianceDays,
                                         int maxContinuous,
                                         String targetStep) {
        // 规则1：总达标天数不足
        if (complianceDays < 4) {
            list.add(new HealthSuggestion(
                    "运动",
                    "步数达标率低",
                    String.format("本周仅%d天步数达标（目标%s步），建议：\n- 增加步行通勤时间\n- 设置每小时站立提醒",
                            complianceDays, targetStep),
                    2
            ));
        }

        // 规则2：连续达标表现优秀
        if (maxContinuous >= 5) {
            list.add(new HealthSuggestion(
                    "运动",
                    "优秀运动习惯",
                    String.format("连续%d天达标！保持规律运动习惯", maxContinuous),
                    3
            ));
        }

        // 规则3：单日步数异常高
        // （假设存在maxStep字段）
    }

    private void generateSleepSuggestions(List<HealthSuggestion> list,
                                          int goodDays,
                                          int lateDays,
                                          LocalDateTime earliest,
                                          LocalDateTime latest) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");

        // 规则1：晚睡天数过多
        if (lateDays >= 3) {
            list.add(new HealthSuggestion(
                    "睡眠",
                    "作息不规律",
                    String.format("本周有%d天晚于22点入睡，最晚至%s\n建议：\n- 睡前1小时避免蓝光\n- 固定起床时间",
                            lateDays, latest.format(formatter)),
                    2
            ));
        }

        // 规则2：睡眠时长不足
        if (goodDays < 5) {
            list.add(new HealthSuggestion(
                    "睡眠",
                    "睡眠时长不足",
                    String.format("仅%d天睡眠在7-9小时健康区间\n建议：\n- 午休不超过30分钟\n- 保持睡眠环境黑暗", goodDays),
                    2
            ));
        }
    }

    private void generateExerciseSuggestions(List<HealthSuggestion> list,
                                             int goalDays,
                                             double maxTime,
                                             double minTime,
                                             double target) {
        // 规则1：达标天数不足
        if (goalDays < 3) {
            list.add(new HealthSuggestion(
                    "运动",
                    "运动时长不足",
                    String.format("本周仅%d天达成目标（推荐%.0f分钟）\n建议：\n- 拆分运动时段\n- 尝试家庭健身课程",
                            goalDays, target),
                    2
            ));
        }

        // 规则2：存在过度运动
        if (maxTime > target * 1.5) {
            list.add(new HealthSuggestion(
                    "运动",
                    "注意运动强度",
                    String.format("检测到单日运动%.0f分钟（目标%.0f），注意：\n- 运动后充分拉伸\n- 保证休息恢复",
                            maxTime, target),
                    3
            ));
        }
    }

    private void generateBpSuggestions(List<HealthSuggestion> list,
                                       int maxSbp,
                                       int highDays) {
        // 规则1：单次血压超标
        if (maxSbp > 140) {
            list.add(new HealthSuggestion(
                    "健康监测",
                    "血压异常警报",
                    String.format("最高收缩压%dmmHg（正常<140）\n建议：\n- 减少钠盐摄入\n- 避免情绪激动", maxSbp),
                    1  // 最高优先级
            ));
        }

        // 规则2：频繁血压升高
        if (highDays >= 3) {
            list.add(new HealthSuggestion(
                    "健康监测",
                    "持续性高血压风险",
                    String.format("%d天检测到血压偏高\n建议：\n- 每日固定时间测量\n- 及时就医检查", highDays),
                    1
            ));
        }
    }
    private void generateSleepQualitySuggestions(List<HealthSuggestion> list,
                                                 double avgDeepSleep,
                                                 double avgRemSleep,
                                                 int lowDeepDays,
                                                 int lowRemDays,
                                                 int highLightDays) {
        // 规则1：深度睡眠不足
        if (avgDeepSleep < 15.0) {
            String advice = String.format(
                    "🌙 深度睡眠不足（平均%.1f%% < 推荐15%%）\n建议：\n" +
                            "- 保持卧室完全黑暗\n" +
                            "- 睡前避免咖啡因摄入\n" +
                            "- 尝试白噪音助眠",
                    avgDeepSleep
            );
            list.add(new HealthSuggestion("睡眠质量", "深度睡眠需改善", advice, 2));
        }

        // 规则2：REM睡眠不足
        if (avgRemSleep < 20.0) {
            String advice = String.format(
                    "💤 REM睡眠不足（平均%.1f%% < 推荐20%%）\n影响：\n" +
                            "- 记忆力巩固\n- 情绪调节\n建议：\n" +
                            "- 减少酒精摄入\n- 保持规律作息",
                    avgRemSleep
            );
            list.add(new HealthSuggestion("睡眠质量", "REM睡眠不足", advice, 2));
        }

        // 规则3：浅睡眠占比过高
        if (highLightDays >= 3) {
            String advice = String.format(
                    "😴 浅睡眠时间过长（%d天>60%%）\n建议：\n" +
                            "- 更换更舒适的寝具\n" +
                            "- 避免睡前使用电子设备\n" +
                            "- 尝试冥想放松训练",
                    highLightDays
            );
            list.add(new HealthSuggestion("睡眠质量", "浅睡眠过多", advice, 2));
        }

        // 规则4：优质睡眠奖励（修正条件）
        if (avgDeepSleep >= 20.0 && avgRemSleep >= 25.0) {
            list.add(new HealthSuggestion(
                    "睡眠质量",
                    "优质睡眠保持者",
                    String.format("🎉 您的睡眠结构优秀（深度%.1f%%，REM%.1f%%），继续保持！", avgDeepSleep, avgRemSleep),
                    3
            ));
        }
    }
    public static void main(String[] args) {
        System.out.println(LocalDateTime.now().isAfter(LocalDateTime.now().minusHours(3)));
    }
}
